import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.0
import QtQuick.Controls.Private 1.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
import QtWebEngine 1.2
import Qt.labs.settings 1.0

import com.yihu.xchat.model 1.0

Rectangle {
    id: webPageContainer

    anchors.fill: parent

    Settings {
        id : appSettings

        property bool autoLoadImages: false // loadImages.checked;
        property bool javaScriptEnabled: false // javaScriptEnabled.checked;
        property bool errorPageEnabled: false // errorPageEnabled.checked;
        property bool pluginsEnabled: false // pluginsEnabled.checked;
        property bool fullScreenSupportEnabled: false // fullScreenSupportEnabled.checked;
        property bool autoLoadIconsForPage: false // autoLoadIconsForPage.checked;
        property bool touchIconsEnabled: false // touchIconsEnabled.checked;
    }

    StyleItem { id: styleItem }     // 使用Style元素判断程序所在的平台. 当样式为 "mac", ToolButtons不支持焦点操作

    property QtObject browserRoot
    property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : null
    property bool platformIsMac: styleItem.style == "mac"
    property int previousVisibility: 1

    //-----------------------------------
    // 操作
    //-----------------------------------
    Action {
        shortcut: "Ctrl+D"
        onTriggered: {
            downloadView.visible = !downloadView.visible
        }
    }
    Action {
        id: focus
        shortcut: "Ctrl+L"
        onTriggered: {
            addressBar.forceActiveFocus();
            addressBar.selectAll();
        }
    }
    Action {
        shortcut: StandardKey.Refresh
        onTriggered: {
            if (currentWebView)
                currentWebView.reload()
        }
    }
    Action {
        shortcut: StandardKey.AddTab
        onTriggered: {
            tabs.createEmptyTab(currentWebView.profile)
            tabs.currentIndex = tabs.count - 1
            addressBar.forceActiveFocus();
            addressBar.selectAll();
        }
    }
    Action {
        shortcut: StandardKey.Close
        onTriggered: {
            currentWebView.triggerWebAction(WebEngineView.RequestClose);
        }
    }
    Action {
        shortcut: "Escape"
        onTriggered: {
            if (currentWebView.state == "FullScreen") {
                webPageContainer.visibility = webPageContainer.previousVisibility
                fullScreenNotification.hide()
                currentWebView.triggerWebAction(WebEngineView.ExitFullScreen);
            }
        }
    }
    Action {
        shortcut: "Ctrl+0"
        onTriggered: currentWebView.zoomFactor = 1.0;
    }
    Action {
        shortcut: StandardKey.ZoomOut
        onTriggered: currentWebView.zoomFactor -= 0.1;
    }
    Action {
        shortcut: StandardKey.ZoomIn
        onTriggered: currentWebView.zoomFactor += 0.1;
    }

    Action {
        shortcut: StandardKey.Copy
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Copy)
    }
    Action {
        shortcut: StandardKey.Cut
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Cut)
    }
    Action {
        shortcut: StandardKey.Paste
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Paste)
    }
    Action {
        shortcut: "Shift+"+StandardKey.Paste
        onTriggered: currentWebView.triggerWebAction(WebEngineView.PasteAndMatchStyle)
    }
    Action {
        shortcut: StandardKey.SelectAll
        onTriggered: currentWebView.triggerWebAction(WebEngineView.SelectAll)
    }
    Action {
        shortcut: StandardKey.Undo
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Undo)
    }
    Action {
        shortcut: StandardKey.Redo
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Redo)
    }
    Action {
        shortcut: StandardKey.Back
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Back)
    }
    Action {
        shortcut: StandardKey.Forward
        onTriggered: currentWebView.triggerWebAction(WebEngineView.Forward)
    }

    ToolBar {
        id: navigationBar
        height: 40

        RowLayout {
            anchors.fill: parent;

            // 浏览历史
            ToolButton {
                visible: false
                enabled: currentWebView && (currentWebView.canGoBack || currentWebView.canGoForward)
                menu:Menu {
                    id: historyMenu

                    /*Instantiator {
                        model: currentWebView && currentWebView.navigationHistory.items
                        MenuItem {
                            text: model.title
                            onTriggered: currentWebView.goBackOrForward(model.offset)
                            checkable: !enabled
                            checked: !enabled
                            enabled: model.offset
                        }

                        onObjectAdded: historyMenu.insertItem(index, object)
                        onObjectRemoved: historyMenu.removeItem(object)
                    }*/
                }
            }

            // 导航按钮
            ToolButton {
                id: backButton
                iconSource: "qrc:/images/browser-left.png"
                onClicked: currentWebView.goBack()
                enabled: currentWebView && currentWebView.canGoBack
                activeFocusOnTab: !webPageContainer.platformIsMac
            }
            ToolButton {
                id: forwardButton
                iconSource: "qrc:/images/browser-right.png"
                onClicked: currentWebView.goForward()
                enabled: currentWebView && currentWebView.canGoForward
                activeFocusOnTab: !webPageContainer.platformIsMac
            }
            ToolButton {
                id: reloadButton
                iconSource: currentWebView && currentWebView.loading ? "qrc:/images/browser-stop.png" : "qrc:/images/browser-refresh.png"
                onClicked: currentWebView && currentWebView.loading ? currentWebView.stop() : currentWebView.reload()
                activeFocusOnTab: !webPageContainer.platformIsMac
            }
            ToolButton {
                id: homeButton
                iconSource: "qrc:/images/browser-home.png"
                onClicked: currentWebView.url = ConfigSingleton.cloudDesktopHome
                enabled: true
                activeFocusOnTab: !webPageContainer.platformIsMac
            }

            // 地址栏
            TextField {
                id: addressBar

                readOnly: true

                Image {
                    anchors.verticalCenter: addressBar.verticalCenter;
                    x: 5
                    z: 2
                    id: faviconImage
                    width: 16; height: 16
                    sourceSize: Qt.size(width, height)
                    source: currentWebView && currentWebView.icon
                }

                style: TextFieldStyle {
                    padding {
                        left: 26;
                    }
                }

                focus: true
                Layout.fillWidth: true
                text: currentWebView && currentWebView.url
                onAccepted: currentWebView.url = utils.fromUserInput(text)
            }

            ToolButton {
                id: settingsMenuButton
                menu: Menu {
                    MenuItem {
                        id: loadImages
                        text: "Autoload images"
                        checkable: true
                        checked: WebEngine.settings.autoLoadImages
                    }
                    MenuItem {
                        id: javaScriptEnabled
                        text: "JavaScript On"
                        checkable: true
                        checked: WebEngine.settings.javascriptEnabled
                    }
                    MenuItem {
                        id: errorPageEnabled
                        text: "ErrorPage On"
                        checkable: true
                        checked: WebEngine.settings.errorPageEnabled
                    }
                    MenuItem {
                        id: pluginsEnabled
                        text: "Plugins On"
                        checkable: true
                        checked: true
                    }
                    MenuItem {
                        id: fullScreenSupportEnabled
                        text: "FullScreen On"
                        checkable: true
                        checked: WebEngine.settings.fullScreenSupportEnabled
                    }
                    MenuItem {
                        id: offTheRecordEnabled
                        text: "Off The Record"
                        checkable: true
                        checked: currentWebView.profile.offTheRecord
                        onToggled: currentWebView.profile = checked ? otrProfile : defaultProfile;
                    }
                    MenuItem {
                        id: httpDiskCacheEnabled
                        text: "HTTP Disk Cache"
                        checkable: !currentWebView.profile.offTheRecord
                        checked: (currentWebView.profile.httpCacheType == WebEngineProfile.DiskHttpCache)
                        onToggled: currentWebView.profile.httpCacheType = checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache
                    }
                    MenuItem {
                        id: autoLoadIconsForPage
                        text: "Icons On"
                        checkable: true
                        checked: WebEngine.settings.autoLoadIconsForPage
                    }
                    MenuItem {
                        id: touchIconsEnabled
                        text: "Touch Icons On"
                        checkable: true
                        checked: WebEngine.settings.touchIconsEnabled
                        enabled: autoLoadIconsForPage.checked
                    }
                }
            }
        }
    }

    // 进度条
    ProgressBar {
        id: progressBar

        height: 3
        width: parent.width
        anchors {
            left: parent.left
            top: navigationBar.bottom
            right: parent.right
        }

        style: ProgressBarStyle {
            background: Rectangle {
                radius: 2
                color: "white"
            }

            progress: Rectangle {
                color: "#F75000"
            }
        }

        z: 2;
        minimumValue: 0
        maximumValue: 100
        value: (currentWebView && currentWebView.loadProgress <= 100) ? currentWebView.loadProgress : 0
    }

    TabView {
        id: tabs

        anchors.top: progressBar.bottom
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.left: parent.left

        Component.onCompleted: createEmptyTab(defaultProfile)

        Component {
            id: tabComponent

            WebEngineView {
                id: webEngineView
                focus: true

                onLinkHovered: {
                    if (hoveredUrl == "")
                        resetStatusText.start()
                    else {
                        resetStatusText.stop()
                        statusText.text = hoveredUrl
                    }
                }

                states: [
                    State {
                        name: "FullScreen"
                        PropertyChanges {
                            target: tabs
                            frameVisible: false
                            tabsVisible: false
                        }
                        PropertyChanges {
                            target: navigationBar
                            visible: false
                        }
                    }
                ]
                settings.autoLoadImages: appSettings.autoLoadImages
                settings.javascriptEnabled: appSettings.javaScriptEnabled
                settings.errorPageEnabled: appSettings.errorPageEnabled
                settings.pluginsEnabled: appSettings.pluginsEnabled
                settings.fullScreenSupportEnabled: appSettings.fullScreenSupportEnabled
                settings.autoLoadIconsForPage: appSettings.autoLoadIconsForPage
                settings.touchIconsEnabled: appSettings.touchIconsEnabled

                onCertificateError: {
                    error.defer()
                    sslDialog.enqueue(error)
                }

                onNewViewRequested: {
                    if (!request.userInitiated)
                        print("Warning: Blocked a popup window.")
                    else if (request.destination == WebEngineView.NewViewInTab) {
                        var tab = tabs.createEmptyTab(currentWebView.profile)
                        tabs.currentIndex = tabs.count - 1
                        request.openIn(tab.item)
                    } else if (request.destination == WebEngineView.NewViewInBackgroundTab) {
                        var tab = tabs.createEmptyTab(currentWebView.profile)
                        request.openIn(tab.item)
                    } else if (request.destination == WebEngineView.NewViewInDialog) {
                        var dialog = browserRoot.createDialog(currentWebView.profile)
                        request.openIn(dialog.currentWebView)
                    } else {
                        var window = browserRoot.createWindow(currentWebView.profile)
                        request.openIn(window.currentWebView)
                    }
                }

                onFullScreenRequested: {
                    if (request.toggleOn) {
                        webEngineView.state = "FullScreen"
                        webPageContainer.previousVisibility = webPageContainer.visibility
                        webPageContainer.showFullScreen()
                        fullScreenNotification.show()
                    } else {
                        webEngineView.state = ""
                        webPageContainer.visibility = webPageContainer.previousVisibility
                        fullScreenNotification.hide()
                    }
                    request.accept()
                }

                onRenderProcessTerminated: {
                    var status = ""
                    switch (terminationStatus) {
                    case WebEngineView.NormalTerminationStatus:
                        status = "(normal exit)"
                        break;
                    case WebEngineView.AbnormalTerminationStatus:
                        status = "(abnormal exit)"
                        break;
                    case WebEngineView.CrashedTerminationStatus:
                        status = "(crashed)"
                        break;
                    case WebEngineView.KilledTerminationStatus:
                        status = "(killed)"
                        break;
                    }

                    console.debug("Render process exited with code " + exitCode + " " + status)
                    reloadTimer.running = true
                }

                onWindowCloseRequested: {
                    if (tabs.count == 1)
                        webPageContainer.close()
                    else
                        tabs.removeTab(tabs.currentIndex)
                }

                Timer {
                    id: reloadTimer
                    interval: 0
                    running: false
                    repeat: false
                    onTriggered: currentWebView.reload()
                }
            }
        }

        function createEmptyTab(profile) {
            var tab = addTab("", tabComponent)

            // We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately.
            tab.active = true
            tab.title = Qt.binding(function() { return tab.item.title.length > 17 ? tab.item.title.substring(0, 17) + "..." : tab.item.title })
            tab.item.profile = profile

            return tab
        }
    }

    // 证书验证失败提示消息框
    MessageDialog {
        id: sslDialog

        icon: StandardIcon.Warning
        standardButtons: StandardButton.No | StandardButton.Yes
        title: "Server's certificate not trusted"
        text: "Do you wish to continue?"
        detailedText: "If you wish so, you may continue with an unverified certificate. " +
                      "Accepting an unverified certificate means " +
                      "you may not be connected with the host you tried to connect to.\n" +
                      "Do you wish to override the security check and continue?"
        onYes: {
            certErrors.shift().ignoreCertificateError()
            presentError()
        }
        onNo: reject()
        onRejected: reject()

        property var certErrors: []

        function reject(){
            certErrors.shift().rejectCertificate()
            presentError()
        }
        function enqueue(error){
            certErrors.push(error)
            presentError()
        }
        function presentError(){
            visible = certErrors.length > 0
        }
    }

    FullScreenNotification {
        id: fullScreenNotification
    }

    // 状态气泡，当加载页面时，显示进度，加载完成后显示鼠标位置处的链接地址
    Rectangle {
        id: statusBubble
        color: "oldlace"

        property int padding: 8

        anchors.left: parent.left
        anchors.bottom: parent.bottom
        width: statusText.paintedWidth + padding
        height: statusText.paintedHeight + padding

        Text {
            id: statusText
            anchors.centerIn: statusBubble
            elide: Qt.ElideMiddle

            Timer {
                id: resetStatusText
                interval: 750
                onTriggered: statusText.text = ""
            }
        }
    }

    // 文件下载视图
    DownloadView {
        id: downloadView
        visible: false
        anchors.fill: parent
    }

    function onDownloadRequested(download) {
        downloadView.visible = true
        downloadView.append(download)
        download.accept()
    }
}
